Exploratory Data Analysis
\(\hspace{0.3cm}\) More articles: \(\hspace{0.1cm}\) Estadistica4all
\(\hspace{0.3cm}\) Author: \(\hspace{0.1cm}\) Fabio Scielzo Ortiz
\(\hspace{0.3cm}\) If you use this article, please, reference it:
\(\hspace{0.5cm}\) Scielzo Ortiz, Fabio. (2023). Exploratory Data Analysis. http://estadistica4all.com/Articulos/EDA.html
It’s recommended open the article in a computer or tablet.
1 Exploratory Data Analysis (EDA)
Exploratory data analysis (análisis de datos exploratorio) hace referencia analisis estadistico, principalmente descriptivo, de un conjunto de datos.
A continuación se va a proponer una metodologia (unos pasos a seguir) para desarrollar un EDA.
A continuación cargamos el data-set al que vamos a aplicar un EDA
import pandas as pd
Netflix_Data = pd.read_csv('titles.csv')Hacemos un head() del data-set para ver que pinta tiene:
Netflix_Data.head()| id | title | type | description | release_year | age_certification | runtime | genres | production_countries | seasons | imdb_id | imdb_score | imdb_votes | tmdb_popularity | tmdb_score | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | ts300399 | Five Came Back: The Reference Films | SHOW | This collection includes 12 World War II-era p… | 1945 | TV-MA | 51 | [‘documentation’] | [‘US’] | 1.0 | NaN | NaN | NaN | 0.600 | NaN |
| 1 | tm84618 | Taxi Driver | MOVIE | A mentally unstable Vietnam War veteran works … | 1976 | R | 114 | [‘drama’, ‘crime’] | [‘US’] | NaN | tt0075314 | 8.2 | 808582.0 | 40.965 | 8.179 |
| 2 | tm154986 | Deliverance | MOVIE | Intent on seeing the Cahulawassee River before… | 1972 | R | 109 | [‘drama’, ‘action’, ‘thriller’, ‘european’] | [‘US’] | NaN | tt0068473 | 7.7 | 107673.0 | 10.010 | 7.300 |
| 3 | tm127384 | Monty Python and the Holy Grail | MOVIE | King Arthur, accompanied by his squire, recrui… | 1975 | PG | 91 | [‘fantasy’, ‘action’, ‘comedy’] | [‘GB’] | NaN | tt0071853 | 8.2 | 534486.0 | 15.461 | 7.811 |
| 4 | tm120801 | The Dirty Dozen | MOVIE | 12 American military prisoners in World War II… | 1967 | NaN | 150 | [‘war’, ‘action’] | [‘GB’, ‘US’] | NaN | tt0061578 | 7.7 | 72662.0 | 20.398 | 7.600 |
2 Esctructura del data-set
2.1 Tamaño
Lo primero es determinar el tamaño del data-set al que se le aplica el EDA. El tamaño de un data-set se puede concebir como su nº de filas y columnas.
Netflix_Data.shape(5850, 15)
El data set tiene 5850 filas (observaciones) y 15 columnas (variables).
2.2 Descripción conceptual de las variables
Esta data-set contieene información sobre 15 variables para 5850 títulos de Netflix.
La siguiente tabla contiene una breve descripción de las variables del data-set:
| Variable | Descripción | Tipo |
|---|---|---|
| id | The title ID on JustWatch | Identificador |
| title | The name of the title | Texto |
| type | TV show or movie | Categórica |
| description | A brief description | Texto |
| release_year | Año de lanzamiento | Cuantitativa |
| age_certification | La calificación de edad | Categórica |
| runtime | el nº de episiodios (show), el tiempo de durancion en minutos (movie) | Cuantitativa |
| genres | A list of genres | Categórica |
| production_countries | A list of countries that produced the title | Categórica |
| seasons | Number of seasons if it’s a SHOW | Cuantitativa |
| imdb_id | The title ID on IMDB | Identificador |
| imdb_score | Puntuación en IMDB | Cuantitativa |
| imdb_votes | nº de votos en IMDB | Cuantitativa |
| tmdb_popularity | Popularity on TMDB | Cuantitativa |
| tmdb_score | Puntuación en TMDB | Cuantitativa |
2.3 Tipo de variables
Ahora vamos a ver de que tipo son cada una de las 15 variables en Python
Netflix_Data.info()<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5850 entries, 0 to 5849
Data columns (total 15 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 id 5850 non-null object
1 title 5849 non-null object
2 type 5850 non-null object
3 description 5832 non-null object
4 release_year 5850 non-null int64
5 age_certification 3231 non-null object
6 runtime 5850 non-null int64
7 genres 5850 non-null object
8 production_countries 5850 non-null object
9 seasons 2106 non-null float64
10 imdb_id 5447 non-null object
11 imdb_score 5368 non-null float64
12 imdb_votes 5352 non-null float64
13 tmdb_popularity 5759 non-null float64
14 tmdb_score 5539 non-null float64
dtypes: float64(5), int64(2), object(8)
memory usage: 685.7+ KB
El Dtype object es el típico de variables categoricas, identificadores o texto.
El Dtype float64 y int64 es típico de variables cuantitativas (continuas y discretas, respectivamente).
2.4 Valores faltantes (NA)
Ahora vamos a calcular la proporcion de valores faltantes sobre el total de datos, para cada una de las variables:
Prop_NA = Netflix_Data.isnull().sum() / len(Netflix_Data)
Prop_NAid 0.000000
title 0.000171
type 0.000000
description 0.003077
release_year 0.000000
age_certification 0.447692
runtime 0.000000
genres 0.000000
production_countries 0.000000
seasons 0.640000
imdb_id 0.068889
imdb_score 0.082393
imdb_votes 0.085128
tmdb_popularity 0.015556
tmdb_score 0.053162
dtype: float64
Podemos ver que hay variables como age_certification con una alta proporción de valores faltantes (44.77%).
seasonsería la variable con mayor proporción de valores faltantes, pero esto se debe a que solo esta definida para las series (type=SHOW)
En este artículo no se hará un tratamiento de los valores faltantes, el cual será expuesto en un futuro articulo sobre pre-procesamiento de datos.
3 Descripción Estadistica Básica
A continuación vamos a realizar una descripción estadistica básica de las variables, a traves de dicersos estadisticos básicos.
3.1 Estadisticos básicos para las variables cuantitativas
Para las variables cuantitativas:
Netflix_Data.describe()| release_year | runtime | seasons | imdb_score | imdb_votes | tmdb_popularity | tmdb_score | |
|---|---|---|---|---|---|---|---|
| count | 5850.000000 | 5850.000000 | 2106.000000 | 5368.000000 | 5.352000e+03 | 5759.000000 | 5539.000000 |
| mean | 2016.417094 | 76.888889 | 2.162868 | 6.510861 | 2.343938e+04 | 22.637925 | 6.829175 |
| std | 6.937726 | 39.002509 | 2.689041 | 1.163826 | 9.582047e+04 | 81.680263 | 1.170391 |
| min | 1945.000000 | 0.000000 | 1.000000 | 1.500000 | 5.000000e+00 | 0.009442 | 0.500000 |
| 25% | 2016.000000 | 44.000000 | 1.000000 | 5.800000 | 5.167500e+02 | 2.728500 | 6.100000 |
| 50% | 2018.000000 | 83.000000 | 1.000000 | 6.600000 | 2.233500e+03 | 6.821000 | 6.900000 |
| 75% | 2020.000000 | 104.000000 | 2.000000 | 7.300000 | 9.494000e+03 | 16.590000 | 7.537500 |
| max | 2022.000000 | 240.000000 | 42.000000 | 9.600000 | 2.294231e+06 | 2274.044000 | 10.000000 |
3.2 Estadisticos básicos para las variables categóricas
Para las variables categóricas (no cuantitativas, en general) :
Netflix_Data.loc[: , ['title', 'description', 'age_certification', 'genres', 'production_countries' ]].describe()| title | description | age_certification | genres | production_countries | |
|---|---|---|---|---|---|
| count | 5849 | 5832 | 3231 | 5850 | 5850 |
| unique | 5798 | 5829 | 11 | 1726 | 452 |
| top | The Gift | Five families struggle with the ups and downs … | TV-MA | [‘comedy’] | [‘US’] |
| freq | 3 | 2 | 883 | 484 | 1959 |
3.3 Gráficos conjuntos para las variables cuantitativas
En esta seccion vamos a hacer un analisis gráfico básico de las variables cuantitativas, consideradas de manera conjunta.
Cargamos las librerias necesarias para los gráficos:
import numpy as np
import seaborn as sns
import matplotlib as mpl
import matplotlib.pyplot as plt3.3.1 Histograma conjunto de las variables cuantitativas
Vamos a generar un grafico con un histograma para cada una de las variables cuantitativas:
fig, axs = plt.subplots(3, 3, figsize=(11, 11))
p1 = sns.histplot(data=Netflix_Data, x="release_year", stat="proportion", bins=15, color="skyblue", ax=axs[0, 0])
p2 = sns.histplot(data=Netflix_Data, x="runtime", stat="proportion", bins=15, color="olive", ax=axs[0, 1])
p2.axes.set(xlabel='runtime', ylabel=' ')
p3 = sns.histplot(data=Netflix_Data, x="seasons", stat="proportion", bins=15, color="blue", ax=axs[0, 2])
p3.axes.set(xlabel='seasons', ylabel=' ')
p4 = sns.histplot(data=Netflix_Data, x="imdb_score", stat="proportion", bins=15, color="teal", ax=axs[1, 0])
p4.axes.set(xlabel='imdb_score', ylabel=' ')
p5 = sns.histplot(data=Netflix_Data, x="imdb_votes", stat="proportion", bins=15, color="purple", ax=axs[1, 1])
p5.axes.set(xlabel='imdb_votes', ylabel=' ')
p6 = sns.histplot(data=Netflix_Data, x="tmdb_popularity", stat="proportion", bins=15, color="pink", ax=axs[1, 2])
p6.axes.set(xlabel='tmdb_popularity', ylabel=' ')
p7 = sns.histplot(data=Netflix_Data, x="tmdb_score", stat="proportion", bins=15, color="red", ax=axs[2, 0])
p7.axes.set(xlabel='tmdb_score', ylabel=' ')
fig.savefig('p1.png', format='png', dpi=1200)
plt.show()Histograma conjunto de las variables cuantitativas
3.3.2 Box-Plot conjunto de las variables cuantitativas
Vamos a generar un grafico con un box-plot para cada una de las variables cuantitativas:
fig, axs = plt.subplots(3, 3, figsize=(11, 11))
p1 = sns.boxplot(data=Netflix_Data, x="release_year", color="skyblue", ax=axs[0, 0])
p2 = sns.boxplot(data=Netflix_Data, x="runtime", color="olive", ax=axs[0, 1])
p2.axes.set(xlabel='runtime', ylabel=' ')
p2.set_xticks( range(int(Netflix_Data['runtime'].min()) , int(Netflix_Data['runtime'].max()) , 100) )
p2.set_yticks( np.arange(0, 1, 0.1) )
p3 = sns.boxplot(data=Netflix_Data, x="seasons", color="blue", ax=axs[0, 2])
p3.axes.set(xlabel='seasons', ylabel=' ')
p4 = sns.boxplot(data=Netflix_Data, x="imdb_score", color="teal", ax=axs[1, 0])
p4.axes.set(xlabel='imdb_score', ylabel=' ')
p4.set_xticks( range(int(Netflix_Data['imdb_score'].min()) , int(Netflix_Data['imdb_score'].max()) , 300) )
p4.set_yticks( np.arange(0, 1, 0.1) )
p5 = sns.boxplot(data=Netflix_Data, x="imdb_votes", color="purple", ax=axs[1, 1])
p5.axes.set(xlabel='imdb_votes', ylabel=' ')
p5.set_xticks( range(int(Netflix_Data['imdb_votes'].min()) , int(Netflix_Data['imdb_votes'].max()/2) , 500000) )
p5.set_yticks( np.arange(0, 1, 0.1) )
p6 = sns.boxplot(data=Netflix_Data, x="tmdb_popularity", color="pink", ax=axs[1, 2])
p6.axes.set(xlabel='tmdb_popularity', ylabel=' ')
p6.set_xticks( range(int(Netflix_Data['tmdb_popularity'].min()) , int(Netflix_Data['tmdb_popularity'].max()+1) , 1000) )
p6.set_yticks( np.arange(0, 1, 0.1) )
p7 = sns.boxplot(data=Netflix_Data, x="tmdb_score", color="red", ax=axs[2, 0])
p7.axes.set(xlabel='tmdb_score', ylabel=' ')
p7.set_xticks( range(int(Netflix_Data['tmdb_score'].min()) , int(Netflix_Data['tmdb_score'].max()+1) , 2) )
p7.set_yticks( np.arange(0, 1, 0.1) )
plt.show()Box-Plot conjunto de las variables cuantitativas
3.3.3 Empirical-Cumulative-Distribution-Function-Plot conjunto de las variables cuantitativas
Vamos a generar un grafico con un ECDF-plot para cada una de las variables cuantitativas:
fig, axs = plt.subplots(3, 3, figsize=(11, 11))
p1 = sns.ecdfplot(data=Netflix_Data, x="release_year", color="skyblue", ax=axs[0, 0])
p1.set_xticks( range(int(Netflix_Data['release_year'].min()) , int(Netflix_Data['release_year'].max()+20) , 20) )
p1.set_yticks( np.arange(0, 1, 0.1) )
p2 = sns.ecdfplot(data=Netflix_Data, x="runtime", color="olive", ax=axs[0, 1])
p2.axes.set(xlabel='runtime', ylabel=' ')
p2.set_xticks( range(int(Netflix_Data['runtime'].min()) , int(Netflix_Data['runtime'].max()) , 100) )
p2.set_yticks( np.arange(0, 1, 0.1) )
p3 = sns.ecdfplot(data=Netflix_Data, x="seasons", color="blue", ax=axs[0, 2])
p3.axes.set(xlabel='seasons', ylabel=' ')
p3.set_xticks( range(int(Netflix_Data['seasons'].min()) , int(Netflix_Data['seasons'].max()) , 4) )
p3.set_yticks( np.arange(0, 1, 0.1) )
p4 = sns.ecdfplot(data=Netflix_Data, x="imdb_score", color="teal", ax=axs[1, 0])
p4.axes.set(xlabel='imdb_score', ylabel=' ')
p4.set_xticks( range(int(Netflix_Data['imdb_score'].min()) , int(Netflix_Data['imdb_score'].max()) , 300) )
p4.set_yticks( np.arange(0, 1, 0.1) )
p5 = sns.ecdfplot(data=Netflix_Data, x="imdb_votes", color="purple", ax=axs[1, 1])
p5.axes.set(xlabel='imdb_votes', ylabel=' ')
p5.set_xticks( range(int(Netflix_Data['imdb_votes'].min()) , int(Netflix_Data['imdb_votes'].max()/2) , 500000) )
p5.set_yticks( np.arange(0, 1, 0.1) )
p6 = sns.ecdfplot(data=Netflix_Data, x="tmdb_popularity", color="pink", ax=axs[1, 2])
p6.axes.set(xlabel='tmdb_popularity', ylabel=' ')
p6.set_xticks( range(int(Netflix_Data['tmdb_popularity'].min()) , int(Netflix_Data['tmdb_popularity'].max()+1) , 1000) )
p6.set_yticks( np.arange(0, 1, 0.1) )
p7 = sns.ecdfplot(data=Netflix_Data, x="tmdb_score", color="red", ax=axs[2, 0])
p7.axes.set(xlabel='tmdb_score', ylabel=' ')
p7.set_xticks( range(int(Netflix_Data['tmdb_score'].min()) , int(Netflix_Data['tmdb_score'].max()+1) , 50) )
p7.set_yticks( np.arange(0, 1, 0.1) )
plt.show()ECDF-Plot conjunto de las variables cuantitativas
3.4 Gráficos conjuntos para las variables categoricas
3.4.1 Bar-plot conjunto de las variables categóricas
Vamos a generar un grafico con un bar-plot para cada una de las variables categóricas, excepto para aquellas cuyo nº de categorias es excesivo, y por tanto no es práctico el gráfico:
fig, axs = plt.subplots(1, 2, figsize=(13, 6))
p1 = sns.countplot(x='type', data=Netflix_Data, ax=axs[0])
p1.set_xticklabels(['Movie', 'Show'])
p1.axes.set(xlabel='type', ylabel='count')
p2 = sns.countplot(x='age_certification', data=Netflix_Data, ax=axs[1])
plt.show()Bar-Plot conjunto de variables categoricas
4 Análisis Estadístico
En la sección anterior se hizo una descripción estadistica básica de las variables del data-set con el que estamos trabajando, pero no se ha hecho ningun analisis de los resultados obtenidos.
En esta seccion además de ampliar la descripción estadistica de los datos, se llevará a cabo un analisis de los resultados obtenidos.